﻿using System;
using System.Linq;
using Mondial2014.Models.Context;
using Mondial2014.Utils.Events;
using Mondial2014.Utils.Extensions;

namespace Mondial2014.Utils
{
    public static class GamblerScoreCalculator
    {
        private static readonly object Sync = new object();

        public static int CalculateScoreForPlayerUntilDate(int gamblerId, DateTime untilDate)
        {
            using (var context = new Mondial2014DbContext())
            {
                return CalculateScoreForPlayerUntilDate(context, gamblerId, untilDate);
            }
        }

        private static int CalculateScoreForPlayerUntilDate(Mondial2014DbContext context, int gamblerId, DateTime untilDate)
        {
            var score = 0;
            var fixtures = context.Fixtures.Where(f => f.Played & f.Date <= untilDate).ToArray();
            foreach (var fixture in fixtures)
            {
                var gameGamble =
                    context.GameGambles.Single(gg => gg.Gambler.Id == gamblerId && gg.Fixture.Number == fixture.Number);
                if (gameGamble.FixtureResult == fixture.GetGameResult())
                {
                    score++;
                }
            }
            return score;
        }

        [EventDispatcher.Subscribe]
        public static void CalculateScores(MatchUpdatedEvent matchUpdatedEvent)
        {
            lock (Sync)
            {
                using (var context = new Mondial2014DbContext())
                {
                    var untilDate =
                        context.Fixtures.Where(f => f.Played).Select(f => f.Date).OrderByDescending(d => d).First();

                    var gamblers = context.Gamblers.ToArray();
                    foreach (var gambler in gamblers)
                    {
                        gambler.GroupsStageScore = CalculateScoreForPlayerUntilDate(context, gambler.Id, untilDate);
                    }

                    context.SaveChanges();
                }

                EventDispatcher.PostEvent(new ScoresUpdatedEvent());
            }
        }
    }
}